package org.sherlock.plugins;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.sherlock.commons.plugins.URLRevealer;
import org.sherlock.commons.plugins.model.Plugin;

/**
 *
 * @author k1773n
 */
public class PluginManager {

    private static PluginManager INSTANCE = null;
    private static final String DB_URL = "jdbc:h2:db/plugins.db";
    private static final String DB_USER = "wd_user";
    private static final String DB_PASS = "wd_pass";
    private Connection connection;

    private PluginManager() {
    }

    public List<Plugin> getPlugins() {
        try {
            ArrayList<Plugin> plugins = new ArrayList<Plugin>();
            String query = "SELECT * FROM plugin ORDER BY name ASC";
            ResultSet rs = getConnection().prepareStatement(query).executeQuery();
            while (rs.next()) {
                plugins.add(new Plugin(rs.getString("author"), rs.getString("description"), rs.getString("name"), rs.getString("version"), rs.getString("file_name"), Plugin.Type.valueOf(rs.getString("type"))));
            }
            return plugins;
        } catch (SQLException ex) {
            Logger.getLogger(PluginManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public boolean pluginExists(String pluginName) {
        try {
            String query = "SELECT COUNT(*) as number FROM plugin WHERE name = ?";
            PreparedStatement pstmt = getConnection().prepareStatement(query);
            pstmt.setString(1, pluginName);
            ResultSet rs = pstmt.executeQuery();
            rs.next();
            return rs.getInt("number") >= 1;
        } catch (SQLException ex) {
            Logger.getLogger(PluginManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return true;
    }

    /**
     * Provides connection to the H2 database. If it does not exist, it will create a new one. How cool is that, eh?
     * @return Connection to the DB, what were you expecting?
     * @throws SQLException If something goes wrong :P
     */
    private Connection getConnection() throws SQLException {
        if (connection == null) {
            boolean create = !(new File("db/plugins.db.h2.db").exists());
            connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
            if (create) {
                createTablePlugins();
            }
        }
        return connection;
    }

    private void createTablePlugins() {
        try {
            String query = "CREATE TABLE plugin (name varchar(" + Integer.MAX_VALUE + "), "
                    + "file_name varchar(" + Integer.MAX_VALUE + "), "
                    + "version varchar(" + Integer.MAX_VALUE + "), "
                    + "type varchar(50), "
                    + "description varchar(" + Integer.MAX_VALUE + "), "
                    + "domain varchar(" + Integer.MAX_VALUE + "), "
                    + "author varchar(" + Integer.MAX_VALUE + "), "
                    + "PRIMARY KEY(file_name))";
            getConnection().prepareStatement(query).execute();
        } catch (SQLException ex) {
            Logger.getLogger(PluginManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public List<Plugin> getRevealerForDomain(String domain) {
        ArrayList<Plugin> plugins = new ArrayList<Plugin>();
        try {
            String query = "SELECT * FROM plugin WHERE domain = ?";
            PreparedStatement pstmt = getConnection().prepareStatement(query);
            pstmt.setString(1, domain.toLowerCase());
            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
            	System.out.println("---> " + rs.getString("name"));
                plugins.add(new Plugin(rs.getString("author"), rs.getString("description"), rs.getString("name"), rs.getString("version"), rs.getString("file_name"), Plugin.Type.valueOf(rs.getString("type"))));
            }
        } catch (SQLException ex) {
            Logger.getLogger(PluginManager.class.getName()).log(Level.SEVERE, null, ex);
        }
        return plugins;
    }

    public void addPlugin(Plugin plugin) {
        try {
        	System.out.println(plugin.getType().name());
            String query = "INSERT INTO plugin (author, description, name, version, file_name, type) VALUES (?,?,?,?,?,?)";
            String queryRevealer = "INSERT INTO plugin (author, description, name, version, file_name, type, domain) VALUES (?,?,?,?,?,?,?)";
            PreparedStatement pstmt = getConnection().prepareStatement(plugin.getType().name().compareTo("REVEALER") == 0 ? queryRevealer : query);
            pstmt.setString(1, plugin.getAuthor());
            pstmt.setString(2, plugin.getDescription());
            pstmt.setString(3, plugin.getName());
            pstmt.setString(4, plugin.getVersion());
            pstmt.setString(5, plugin.getFileName());
            pstmt.setString(6, plugin.getType().toString());
            if (plugin.getType().name().compareTo("REVEALER") == 0) {
            	System.out.println(((URLRevealer) plugin).getDomain());
                pstmt.setString(7, ((URLRevealer) plugin).getDomain());
            }
            pstmt.execute();
        } catch (SQLException ex) {
            Logger.getLogger(PluginManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static synchronized PluginManager getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new PluginManager();
        }
        return INSTANCE;
    }
}
